﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using TomanuExtensions;

namespace RaytracerLib.MathLib.RootFinders
{
    public abstract class DerivativeRootFinder : RootFinder
    {
        protected struct RootState
        {
            public double Root;
            public bool Finded;

            public RootState(double a_x, bool a_finded = true)
            {
                Debug.Assert(a_x.IsNumber());

                Root = a_x;
                Finded = a_finded;
            }
        }

        protected double FindRootFromBothSide(double a_a, double a_b, 
            Func<double, double> a_func, Func<double, RootState> a_root_finder)
        {
            Debug.Assert(a_a < a_b);
            Debug.Assert(a_a.IsNumber());
            Debug.Assert(a_b.IsNumber());

            double ya = a_func(a_a);
            double yb = a_func(a_b);

            if (Math.Abs(ya) < AbsoluteError)
                return a_a;
            if (Math.Abs(yb) < AbsoluteError)
                return a_b;

            if (Math.Sign(ya) * Math.Sign(yb) > 0)
                return Double.PositiveInfinity;

            RootState x1 = a_root_finder(a_a);
            if (x1.Finded && (x1.Root > a_a) && (x1.Root < a_b))
                return x1.Root;

            RootState x2 = a_root_finder(a_b);
            if (x2.Finded && (x2.Root > a_a) && (x2.Root < a_b))
                return x2.Root;

            return Double.PositiveInfinity;
        }
    }
}
